/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.NooLab.itexx.retrieval;

import java.io.InputStream;
import java.io.Serializable;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.NooLab.itexx.app.config.BasicConfigurations;



import org.NooLab.utilities.url.WebURL;

 

 

public class Page implements PageIntf, Serializable {
 
	private static final long serialVersionUID = -341237559391405881L;
	// =================================
	
	// private final static String defaultEncoding = BasicConfigurations.getStringProperty("crawler.default_encoding", "UTF-8");
	private final static String defaultEncoding = "UTF-8";
	// object references ..............

	
	// main variables / properties ....

	// the documents address::object
	WebURL url;

	// plain Html, just as retrieved
	String html="";

	// Data for textual content
	String text="";
	String title="";

	Sections sections, paragraphs;
	
	String temporaryFile="";
	// binary data (e.g, image content)
	// It's null for html pages
	byte[] binaryData;

	String contentType;
	
	List<WebURL> urls;  // FIXME change that !!!
	java.util.Set<String> weblinks ; 
	
	int retrievalStatus = -1;
	boolean saved = false;
	
	// volatile variables .............

	transient private ByteBuffer bBuf;

	private String contextUrl="";

	private boolean isQueryUrl;
	private int currentCollectionIndex;
	private int collectionExpectedSize;

	/** user-based : a particular user query , which could be large and such trigger many packages */
	private String requestID="";  
	/** internal identifier: assigned by the RequestDispatcher */
	private String packageID="";
	
	private String clientId="";
	private String secret="";
	private String knownBufferFile="";

	

	// helper objects .................

	
	
	public String getSecret() {
		return secret;
	}

	// ========================================================================
	public Page(WebURL url) {
		this.url = url;
		init();
	}

	public Page( ) {
		init();
	}
	// ========================================================================
	
	private void init() {
		// 
		sections   = new Sections() ;
		paragraphs = new Sections() ;
	}

	// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

	
	protected boolean loadRaw( final InputStream in, 
						 	   final int totalsize,
						 	   final boolean isBinary) {
		
		if (totalsize > 0) {
			this.bBuf = ByteBuffer.allocate( totalsize + 1024 );
		} else {
			this.bBuf = ByteBuffer.allocate( BasicConfigurations.getIntProperty("fetcher.max_download_size", 80048576) );
		}
		
		final byte[] b = new byte[1024];
		int len;
		double finished = 0;
		try {
			while ((len = in.read(b)) != -1) {
				if (finished + b.length > this.bBuf.capacity()) {
					break;
				}
				this.bBuf.put(b, 0, len);
				finished += len;
			}
		} catch (final BufferOverflowException boe) {
			System.out.println("Page size exceeds maximum allowed.");
			return false;
		} catch (final Exception e) {
			System.err.println(e.getMessage());
			return false;
		}

		this.bBuf.flip();
		if (isBinary) {
			binaryData = new byte[bBuf.limit()];
			bBuf.get(binaryData);
		} else {
			this.html = "";
			this.html += Charset.forName(defaultEncoding).decode(this.bBuf);
			this.bBuf.clear();
			if (this.html.length() == 0) {
				return false;
			}
		}
		
		this.bBuf = ByteBuffer.allocate(1);
		this.bBuf = null;
		return true;
	}



 	public String getHTML() {
		return this.html;
	}

 	public void setHTML( String htmlString) {
		this.html = htmlString;
	}

 	 
 	
	/* (non-Javadoc)
	 * @see org.NooLab.crawler.retrieval.PagesIntf#getText()
	 */
	@Override
	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public Sections getSections() {
		return sections;
	}

	public Sections getParagraphs() {
		return paragraphs;
	}

	public void setLinks( java.util.Set<String> links ){
		weblinks = links;  
	}

	/* (non-Javadoc)
	 * @see org.NooLab.crawler.retrieval.PagesIntf#getLinks()
	 */
	@Override
	public java.util.Set<String> getLinks(){
		return weblinks  ;  
	}
	
	public String getLinksasText(){
		String str,links ="" ;
		Object[] strings;
		 	
		if (weblinks != null) {
			strings = weblinks.toArray();

			for (int i = 0; i < strings.length; i++) {
				links = links + (String) strings[i];
				if (i < strings.length - 1) {
					links = links + "\n";
				}
			}
		}
		return links  ;  
	}
	
	/* (non-Javadoc)
	 * @see org.NooLab.crawler.retrieval.PagesIntf#getLinksCollection()
	 */
	@Override
	public ArrayList<String> getLinksCollection(){
		
		ArrayList<String> linklist = new ArrayList<String> ();
		
		String str,links ="" ;
		Object[] strings;
		 	
		strings = weblinks.toArray();
		
		for (int i=0;i<strings.length;i++){
			linklist.add( (String)strings[i] );
			 
		}
		
		
		return linklist  ;  
	}

	
	
	/* (non-Javadoc)
	 * @see org.NooLab.crawler.retrieval.PagesIntf#getTitle()
	 */
	@Override
	public String getTitle() {
		return title;
	}

	public WebURL getWebURL() {
		return url;
	}

	public int getRetrievalStatus(){
		return retrievalStatus;
	}

	public String getContentType() {
		return contentType;
	}

	@Override
	public ArrayList<String> getTables() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getContextUrl() {
		// 
		return contextUrl;
	}

	@Override
	public void setContextUrl(String urlStr) {
		// 
		contextUrl = urlStr;
	}

	@Override
	public void setIsQueryUrl(boolean flag) {
		// TODO Auto-generated method stub
		isQueryUrl = flag;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public List<WebURL> getURLs() {
		return urls;
	}

	public void setURLs(List<WebURL> urls) {
		this.urls = urls;
	}

	
	
	public void setWebURL(WebURL url) {
		this.url = url;
	}

	public void setPageURL( String urlStr ) {
		 url.setURL(urlStr) ;
	}

	
	// Image or other non-textual pages
	/* (non-Javadoc)
	 * @see org.NooLab.crawler.retrieval.PagesIntf#isBinary()
	 */
	@Override
	public boolean isBinary() {
		return binaryData != null;
	}

	public byte[] getBinaryData() {
		return binaryData;
	}

	public void setRetrievalStatus( int pagefetchstatus ){
		retrievalStatus = pagefetchstatus ;
	}

	public WebURL getUrl() {
		return url;
	}

	public String getTemporaryFile() {
		return temporaryFile;
	}

	@Override
	public void reduceRawGoogleHtml() {
		// TODO Auto-generated method stub
		
	}

	public String getHtml() {
		return html;
	}

	public void setHtml(String html) {
		this.html = html;
	}

	public List<WebURL> getUrls() {
		return urls;
	}

	public void setUrls(List<WebURL> urls) {
		this.urls = urls;
	}

	public java.util.Set<String> getWeblinks() {
		return weblinks;
	}

	public void setWeblinks(java.util.Set<String> weblinks) {
		this.weblinks = weblinks;
	}

	public boolean isSaved() {
		return saved;
	}

	public void setSaved(boolean saved) {
		this.saved = saved;
	}

	public boolean isQueryUrl() {
		return isQueryUrl;
	}

	public void setQueryUrl(boolean isQueryUrl) {
		this.isQueryUrl = isQueryUrl;
	}

	public void setUrl(WebURL url) {
		this.url = url;
	}

	public void setSections(Sections sections) {
		this.sections = sections;
	}

	public void setParagraphs(Sections paragraphs) {
		this.paragraphs = paragraphs;
	}

	public void setTemporaryFile(String temporaryFile) {
		this.temporaryFile = temporaryFile;
	}

	public void setBinaryData(byte[] binaryData) {
		this.binaryData = binaryData;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	
	
	@Override	
	public void setCurrentCollectionIndex(int index) {
		currentCollectionIndex = index;
	}
	@Override
	public int getCurrentCollectionIndex() {
		return currentCollectionIndex;
	}

	
	@Override
	public void setExpectedCollectionSize(int xsize) {
		collectionExpectedSize = xsize;
	}
	@Override
	public int getExpectedCollectionSize() {
		return collectionExpectedSize ;
	}

	public int getCollectionExpectedSize() {
		return collectionExpectedSize;
	}

	public void setCollectionExpectedSize(int collectionExpectedSize) {
		this.collectionExpectedSize = collectionExpectedSize;
	}

	@Override
	public void setInternalClient(String clientId) {
		
		this.clientId = clientId;
	}

	public String getClientId() {
		return clientId;
	}

	public void setClientId(String clientId) {
		this.clientId = clientId;
	}

	@Override
	public String getRequestID() {
		return requestID;
	}
	@Override
	public void setRequestID(String requestID) {
		this.requestID = requestID;
	}
	@Override
	public String getPackageID() {
		return packageID;
	}
	@Override
	public void setPackageID(String packageGuid) {
		this.packageID = packageID;
	}

	@Override
	public void setSecret(String str) {
		// 
		secret = str;
	}

	@Override
	public String getKnownBufferFile() {
		return knownBufferFile;
	}

	@Override
	public void setKnownBufferFile(String filename) {
		
		knownBufferFile = filename ;
	}

}
